package org.simpleframework.aop;

import java.lang.reflect.Method;

import org.aspectj.weaver.tools.PointcutExpression;
import org.aspectj.weaver.tools.PointcutParser;
import org.aspectj.weaver.tools.ShadowMatch;

/**
 * 解析 Aspect 表达式并且定位被织入的目标
 *
 * @author icanci
 * @date Created in 2021/03/04 00:45
 * @version 1.0
 */
public class PointcutLocator {

    /**
     * Pointcut 解析器，直接给它赋值上 Aspectj 的所有表达式，以便支持对众多的表达式的解析
     */
    private PointcutParser     pointcutParser = PointcutParser
        .getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(PointcutParser.getAllSupportedPointcutPrimitives());

    /**
     * 表达式解析器
     */
    private PointcutExpression pointcutExpression;

    public PointcutLocator(String expression) {
        this.pointcutExpression = pointcutParser.parsePointcutExpression(expression);
    }

    /**
     * 判断传入的Class对象是否是Aspect的目标代理类，即匹配Pointcut表达式(初次筛选)
     * @param targetClass 目标类
     * @return 是否匹配
     */
    public boolean roughMatches(Class<?> targetClass) {
        // couldMatchJoinPointsInType 只能校验 within
        // 不能校验 (execution[精确到某个具体的类除外],call,get,set) 面对无法校验的表达式，直接返回true
        return pointcutExpression.couldMatchJoinPointsInType(targetClass);
    }

    /**
     * 判断传入的Method对象是否是Aspect的目标代理方法，即匹配Pointcut表达式(精细筛选)
     * @param method 目标方法
     * @return 是否匹配
     */
    public boolean accurateMatches(Method method) {
        ShadowMatch shadowMatch = pointcutExpression.matchesMethodExecution(method);
        return shadowMatch.alwaysMatches();
    }
}